package com.bac.rentmap.ad.flat.crawler.localaddress;

import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

import com.bac.rentmap.ad.flat.LocalAddress;
import com.bac.rentmap.ad.flat.LocalAddressPrefix;

/**
 * Analyze the whole string to parse address. Source string can contain address
 * with whitespace only.
 * 
 * @author Andrew Osipenko
 */
public class SimpleLocaAddressParser implements LocalAddressParser {
	private static final Logger log = Logger
			.getLogger(SimpleLocaAddressParser.class.getName());
	private static final String DIFFICULT_STREET_WORD_PATTERN = "(?:3-го|50 лет|1-й|2-й)";

	private Pattern addressPattern;
	private Pattern reverseAddressPattern;

	public SimpleLocaAddressParser() {
		List<String> prefixes = LocalAddressPrefix.getSynonymPatterns();
		String prefixesRegex = StringUtils.collectionToDelimitedString(
				prefixes, "|");
		addressPattern = Pattern.compile("\\s*(" + prefixesRegex
				+ ")?\\.?\\s*((?:" + DIFFICULT_STREET_WORD_PATTERN + "\\s)?\\p{L}[\\p{L}\\s]*\\p{L}(?:\\s" + DIFFICULT_STREET_WORD_PATTERN + ")?)\\s*,?\\s*(\\d*)\\s*");
		log.info("Pattern: " + addressPattern);
		reverseAddressPattern = Pattern
				.compile("\\s*((?:" + DIFFICULT_STREET_WORD_PATTERN + "\\s)?\\p{L}[\\p{L}\\s]*\\p{L}(?:\\s" + DIFFICULT_STREET_WORD_PATTERN + ")?)\\s*(?:\\s("
						+ prefixesRegex + ")[\\.\\s,]),?\\s*(\\d*)\\s*");
		log.info("Reverse pattern: " + reverseAddressPattern);
	}

	public LocalAddress parse(String string) {
		string = string + " ";
		LocalAddressPrefix prefix = null;
		String street = null;
		Integer building = null;
		Matcher matcher = addressPattern.matcher(string);
		boolean matchFound = matcher.find();
		if (matchFound) {
			street = matcher.group(2);
			String buildingString = matcher.group(3);
			String prefixString = matcher.group(1);
			if (prefixString == null) {
				Matcher reverseMatcher = reverseAddressPattern.matcher(string);
				if (reverseMatcher.find()) {
					street = reverseMatcher.group(1);
					buildingString = reverseMatcher.group(3);
					prefixString = reverseMatcher.group(2);
				}
			}
			if (prefixString != null) {
				prefix = LocalAddressPrefix.valueOfSynonym(prefixString);
			}
			if (!buildingString.isEmpty()) {
				building = Integer.valueOf(buildingString);
			}
		} else {
			throw new IllegalArgumentException("Can't parse address from "
					+ string);
		}
		LocalAddress res = new LocalAddress(prefix, street, building);
		log.fine("Parsed '" + string + "' to " + res);
		return res;
	}

}
